﻿
using Albatross.Modules;
using Albatross.Shell.Configuration;
using Albatross.Shell.ViewModels;
using Albatross.WPF.Common;
using Albatross.WPF.Common.PubSub;
using Albatross.WPF.Common.ViewModels;
using Albatross.WPF.Common.Views;
using log4net;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace Albatross.Shell {
	public partial class Shell : Window, IViewService {
		public Shell() {
			InitializeComponent();
			SetValue(Attached.ViewServiceProperty, this);
			Workspaces = new ObservableCollection<IWorkspaceConstruct>();
			Publisher = new Publisher();
			DataContext = this;
			this.Loaded += Shell_Loaded;
		}

		#region properties
		public ILog Log = LogManager.GetLogger("Shell");
		public RelayCommand<IViewService> NewWindowCommand { get { return new RelayCommand<IViewService>(svcs => svcs.CreateWindow(null)); } }
		public RelayCommand<IViewService> OptionsCommand { get { return new RelayCommand<IViewService>(svcs => svcs.ShowWorkspace<OptionsViewModel>()); } }
		public RelayCommand<IViewService> SystemCommand { get { return new RelayCommand<IViewService>(svcs => svcs.ShowWorkspace<SystemsViewModel>()); } }
		public RelayCommand<IViewService> AboutCommand { get { return new RelayCommand<IViewService>(svcs => svcs.ShowWorkspace<AboutViewModel>()); } }
		public RelayCommand<IViewService> ExitCommand { get { return new RelayCommand<IViewService>(Exit); } }
		public RelayCommand<IViewService> ManageFavoritesCommand { get { return new RelayCommand<IViewService>(svcs => svcs.ShowWorkspace<ManageFavoritesViewModel>()); } }
		public ObservableCollection<IWorkspaceConstruct> Workspaces { get; private set; }
		#endregion

		#region methods
		void Shell_Loaded(object sender, RoutedEventArgs e) {
			LoadModules();
		}
		void Exit(IViewService svcs) {
			Close();
		}
		void ManageFavorites(IViewService svcs) { }
		void LoadModules() {
			try {
				ShellCfgSection cfgSection = ShellCfgSection.GetConfiguration(false);
				foreach (ModuleCfgElement cfgElement in cfgSection.Modules) {
					try {
						Type type = Type.GetType(cfgElement.ClassName);
						if (type == null) {
							throw new ArgumentException(string.Format("Type {0} not found for module {1}", cfgElement.ClassName, cfgElement.Name));
						}
						object obj = Activator.CreateInstance(type);

						if (obj is IModule) {
							IModule module = (IModule)obj;
							module.Init(App.Current);
							module.Load(MainMenu);
						} else {
							throw new ArgumentException(string.Format("Class {0} for module {1} is not of type IModule", cfgElement.ClassName, cfgElement.Name));
						}
					} catch (Exception err) {
						Log.Error(err);
					}
				}
			} catch (Exception err) {
				throw err;
			}
		}
		#endregion

		#region View Service
		public WPF.Common.PubSub.IPublisher Publisher { get; private set; }
		public void LoadElement(UIElement elem) { }
		public void UnloadElement(UIElement elem) { }
		public void ShowWorkspace(IWorkspaceConstruct construct) {
			if (construct.WorkspaceID != null) {
				foreach (TabItem tab in MainTabControl.Items) {
					IWorkspaceConstruct current = (IWorkspaceConstruct)tab.GetValue(Attached.WorkspaceConstructProperty);
					if (current.ViewModelType == construct.ViewModelType && object.Equals(current.WorkspaceID, construct.WorkspaceID)) {
						tab.IsSelected = true;
						return;
					}
				}
			}
			UserControl view = construct.GetView();
			TabItem item = new TabItem() {
				Content = view,
				DataContext = construct.Build(),
			};
			item.SetBinding(TabItem.HeaderProperty, new Binding("Title"));
			MainTabControl.Items.Add(item);
			item.IsSelected = true;
			item.SetValue(Attached.WorkspaceConstructProperty, construct);
			Workspaces.Add(construct);
			if (construct.Constructed != null) construct.Constructed.AsyncLoadHandler(this);
		}
		public bool CloseWorkspace(IWorkspaceViewModel vm) {
			for (int i = 0; i < MainTabControl.Items.Count; i++) {
				TabItem item = (TabItem)MainTabControl.Items[i];
				if (item.DataContext == vm) {
					try {
						if (ViewServiceExt.TryCloseView(item)) {
							IWorkspaceConstruct construct = (IWorkspaceConstruct)item.GetValue(Attached.WorkspaceConstructProperty);
							Workspaces.Remove(construct);
							MainTabControl.Items.RemoveAt(i);
							return true;
						} else {
							return false;
						}
					} catch (Exception err) {
						ShowErrorMessageBox(err.Message);
						return false;
					}
				}
			}
			return false;
		}
		public bool? ShowDialog(IWorkspaceConstruct construct, int? width, int? height) {
			return ViewServiceExt.ShowDialog<DialogWindow>(this, construct, width, height);
		}
		public void CreateWindow(IWorkspaceConstruct construct) { }
		public void ShowWarningMessageBox(string msg) {
			IInputElement elem = Keyboard.FocusedElement;
			MessageBox.Show(this, msg, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
			if (elem != null) { Keyboard.Focus(elem); }
		}
		public void ShowErrorMessageBox(string msg) {
			IInputElement elem = Keyboard.FocusedElement;
			MessageBox.Show(this, msg, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
			if (elem != null) { Keyboard.Focus(elem); }
		}
		public void ShowInfoMessageBox(string msg) {
			IInputElement elem = Keyboard.FocusedElement;
			MessageBox.Show(this, msg, "Information", MessageBoxButton.OK, MessageBoxImage.Information);
			if (elem != null) { Keyboard.Focus(elem); }
		}
		public bool ShowConfirmationMessageBox(string msg) {
			IInputElement elem = Keyboard.FocusedElement;
			bool value = MessageBox.Show(this, msg, "Confirmation", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK;
			if (elem != null) { Keyboard.Focus(elem); }
			return value;
		}
		#endregion

		private void WorkspaceDropDownMenu_Initialized(object sender, EventArgs e) {
			ContextMenu cm = (ContextMenu)sender;
			NameScope.SetNameScope(cm, NameScope.GetNameScope(this));
		}

		private void WorkspaceDropDownBtn_Click(object sender, RoutedEventArgs e) {
			Button btn = (Button)sender;
			btn.ContextMenu.IsOpen = true;
		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
			TabItem[] array = new TabItem[MainTabControl.Items.Count];
			MainTabControl.Items.CopyTo(array, 0);
			try {
				e.Cancel = !ViewServiceExt.TryCloseView(array);
			} catch (Exception err) {
				ShowErrorMessageBox(err.Message);
				e.Cancel = true;
			}
		}

		private void CloseAllMenuItem_Click(object sender, RoutedEventArgs e) {
			TabItem[] array = new TabItem[MainTabControl.Items.Count];
			MainTabControl.Items.CopyTo(array, 0);
			using (CloseWorkspacesViewModel vm = new CloseWorkspacesViewModel(array)) {
				vm.Seek();
				if (vm.RequireConfirmation) {
					IWorkspaceConstruct construct = WorkspaceConstructExt.CreateByObject(vm);
					ShowDialog(construct, null, null);
					if (vm.Confirmed) {
						vm.Cleanup();
						MainTabControl.Items.Clear();
					}
				} else {
					vm.Cleanup();
					MainTabControl.Items.Clear();
				}
			}
		}
	}
}